package com.seari.aop;

import com.seari.annotation.AppCacheName;
import com.seari.pojo.MessageBean;
import com.seari.service.AppCacheService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;

/**
 * 动态获取数据
 *
 * @author zhangYanKun
 * @date 2018/1/8 20:12
 */
@Component
@Aspect
public class ProxyDataAspect {

    protected static Logger log = LoggerFactory.getLogger(ProxyDataAspect.class);

    @Autowired
    private AppCacheService service;

    /**
     * 切点
     */
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping) && execution(* com.seari.controller.*Controller.*(..))")
    private void parameterPointCut() {
        // 参数校验切点
    }

    /**
     * 动态获取数据
     *
     * @param joinPoint 连接点
     * @param request 入参
     */
    @Around("parameterPointCut() && args(request,..)")
    public Object validateParameter1(ProceedingJoinPoint joinPoint, HttpServletRequest request) {
        // 获取方法调用信息
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        log.info("invoke service [{}.{}], request parameter [{}].", className, methodName, request);
        log.info("args [{}].", args);

        // 判断是否是快照请求
        if(false){
            // 如果是则直接调用飞哥接口
        }else {
            // 缓存名可以写在controller的自定义注解中
            MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
            AppCacheName appCacheName = methodSignature.getMethod().getAnnotation(AppCacheName.class);

            String name = "";
            if(appCacheName == null){
                name = methodName;
            }else {
                name = appCacheName.value();
            }

            // 如果有参数，就将参数拼接到cache的name上
            if(args.length > 0){
                StringBuilder str = new StringBuilder(name);
                for (Object arg : args) {
                    if(!(arg instanceof HttpServletRequest)){
                        String argStr = arg.toString();
                        str.append(argStr.toUpperCase(), 0, 1).append(argStr.substring(1));
                    }
                }
                name = str.toString();
            }

            // 从缓存中取数据
            Object cacheObject = service.getCacheObject(name);

            MessageBean messageBean = new MessageBean();

            // 如果没有数据则执行代码查询数据，并将数据存入缓存
            if(cacheObject == null){
                try {
                    return joinPoint.proceed();
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                    messageBean.setCode("500");
                    messageBean.setMessage("服务器内部错误，请找相关人员修复代码");
                }
            }

            messageBean.setCode("200");
            messageBean.setData(cacheObject);
            if(cacheObject instanceof Collection){
                messageBean.setTotal(((Collection) cacheObject).size());
            }
            return messageBean;
        }

        return null;
    }
}
